<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" type="text/css" href="../index.css">
    <title>Document</title>
</head>
<body>
<div class="container">
    <h3>迭代器模式</h3>
    <p>jq 或 数组中forEach 的实现</p>
    <p>实现两个数组的比较</p>

    <p class="test-nodelist">1</p>
    <p class="test-nodelist">2</p>
    <p class="test-nodelist">3</p>
    <p class="test-nodelist">4</p>
    <p class="test-nodelist">5</p>
    <p class="test-nodelist">6</p>
    <p class="test-nodelist">7</p>
    <p class="test-nodelist">8</p>
</div>
<script>
    (function() {
        // 普通的迭代其模式 内部迭代
        var each = function(ary, cb) {
            for (var i = 0; i < ary.length; i++) {
                if (cb.call(ary[i], i, ary[i]) === false) {
                    break
                }
            }
        }
        var ary = [{name: 'jerry', age: 1}, {name: 'tom', age: 2}];
        each(ary, function(i, item) {
            // console.log(item.age);
            item.age *= 2;
        });
        // console.log(ary);
        var compare = function(ary1, ary2) {
            var flag = true;
            if (ary1.length !== ary2.length) {
                flag = false
            }
            each(ary1, function(i, item) {
                if(item !== ary2[i]) {
                    flag = false
                }
            })
            return flag;
        }
        var tsAry1 = [1, 2, 3];
        var tsAry2 = [1, 2, 4];
        var flag = compare(tsAry1, tsAry2);
        // console.log(flag);

        // 外部迭代器
        // 以闭包的形式返回数组的只指向，取值与判断是否结束的方法
        var iterator = function(ary) {
            var currentIndex = 0,
                next = function() {
                    currentIndex += 1
                },
                getCurrent = function() {
                    return ary[currentIndex]
                },
                isDone = function() {
                    return currentIndex >= ary.length
                };
            return {
                len: ary.length,
                next: next,
                getCurrent: getCurrent,
                isDone: isDone
            }
        };

        var compare2 = function(iterator1, iterator2) {
            var flag = iterator1.len === iterator2.len;
            if (flag) {
                while (!iterator1.isDone() && !iterator2.isDone()) {
                    if (iterator1.getCurrent() !== iterator2.getCurrent()) {
                        flag = false;
                        break;
                    } else {
                        iterator1.next();
                        iterator2.next();
                    }
                }
            }
            return flag;
        }

        var iterator1 = iterator([1, 2, 3]);
        var iterator2 = iterator([1, 2, 3]);
        var isSome = compare2(iterator1, iterator2);
        // console.log(isSome);

        // 迭代类数组对象与字面量对象
        // jquery each jquery的工具方法
        // args is for internal usage only
        /*each: function( obj, callback, args ) {
            var value,
                i = 0,
                length = obj.length,
                isArray = isArraylike( obj );

            // if ( args ) {
            //     if ( isArray ) {
            //         for ( ; i < length; i++ ) {
            //             value = callback.apply( obj[ i ], args );
            //
            //             if ( value === false ) {
            //                 break;
            //             }
            //         }
            //     } else {
            //         for ( i in obj ) {
            //             value = callback.apply( obj[ i ], args );
            //
            //             if ( value === false ) {
            //                 break;
            //             }
            //         }
            //     }
            //
            //     // A special, fast, case for the most common use of each
            // } else {
            //
            // }

            if ( isArray ) {
                for ( ; i < length; i++ ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );

                    if ( value === false ) {
                        break;
                    }
                }
            } else {
                for ( i in obj ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );

                    if ( value === false ) {
                        break;
                    }
                }
            }

            return obj;
        }*/
        var class2type = {};
        var core_toString = class2type.toString;
        each('Boolean Number String Function Array Date RegExp Object Error'.split(' '), function(i, name) {
            class2type['[object ' + name + ']'] = name.toLowerCase()
        })
        var objType = function(obj) {
            if (obj === null) {
                return toString(obj)
            }

            return typeof obj === 'object' || typeof obj === 'function'
                ? class2type[core_toString.call(obj)] || 'object' : typeof obj;
        }
        var isArraylike = function(obj) {
            var type = objType(obj),
                length = obj.length;

            if (obj !== null && obj ===  obj.window) {
                return false
            }

            if (obj.nodeType === 1 && length) {
                return true
            }

            return type === 'array' || type === 'function' && (
                length === 0 || typeof length === 'number' && length > 0 && (length - 1 in obj)
            )
        }

        var $each = function(obj, callback) {
            var value,
                i = 0,
                length = obj.length,
                isArray = isArraylike(obj);
            if (isArray) {
                for ( ; i < length; i++) {
                    value = callback.call(obj[i], i, obj[i]);
                    if (value === false) {
                        break
                    }
                }
            } else {
                for (i in obj) {
                    value = callback.call(obj[i], i, obj[i]);
                    if (value === false) {
                        break;
                    }
                }
            }
        }
        var testAry1 = [{name: 'xyy', age: 2}, {name: 'myy', age: 3}];
        var testObj = {name: 'xyy', age: 18, grade: 12, class: 4};
        $each(testAry1, function(i, sheep) {
            sheep.name = sheep.name + sheep.age
        });
        $each(testObj, function(i, item) {
            console.log(item);
        })
        // console.log(testAry1);
    })()
</script>
</body>
</html>